package com.bw.lib_http

import android.os.Environment
import com.alibaba.android.arouter.launcher.ARouter
import com.bw.lib_base.constants.BaseConst
import com.bw.lib_base.path.RouterPath
import com.tencent.mmkv.MMKV
import okhttp3.*
import okhttp3.MediaType.Companion.toMediaTypeOrNull
import okhttp3.ResponseBody.Companion.toResponseBody
import okhttp3.logging.HttpLoggingInterceptor
import org.json.JSONObject
import retrofit2.Retrofit
import retrofit2.converter.gson.GsonConverterFactory
import java.io.File
import java.net.Proxy
import java.security.SecureRandom
import java.security.cert.X509Certificate
import java.util.concurrent.TimeUnit
import javax.net.ssl.SSLContext
import javax.net.ssl.SSLHandshakeException
import javax.net.ssl.SSLSocketFactory
import javax.net.ssl.X509TrustManager

/**
 * OkHttpClient管理类
 */

object OkHttpClientManager {

    /**
     * 普通的Http请求的客户端
     */

    val httpClientInstance:OkHttpClient by lazy {
        createOkHttpClient()
    }

    fun createOkHttpClient():OkHttpClient{
        var okBuilder=OkHttpClient.Builder()
            .apply {
                connectTimeout(BaseConst.CONNECT_TIME_OUT,TimeUnit.SECONDS)

                readTimeout(BaseConst.READ_TIME_OUT,TimeUnit.SECONDS)

                writeTimeout(BaseConst.WRITE_TIME_OUT,TimeUnit.SECONDS)

                //设置接口请求拦截日志
//                if (BuildConfig.isOpenLog){
//                    addInterceptor(HttpLoggingInterceptor().setLevel(HttpLoggingInterceptor.Level.BODY))//日志拦截器
//                }

                //Header参数拦截器
                addInterceptor(getHeaderInterceptor())

//
//                //服务器异常拦截器
//                addInterceptor(getServiceExceptionInterceptor())
//
//                //添加Https的支持
//                sslSocketFactory(sslSocketFactory, trustManager)
//
//                //设置支持的网络协议
//                protocols(listOf(Protocol.HTTP_2))
//
//                //防止抓包软件获取接口数据
//                proxy(Proxy.NO_PROXY)
//
//                //设置缓存目录
//                val cacheFile= getexternalStoreFile()
//                if (cacheFile != null){
//                    cache(Cache(cacheFile,10 * 1024 * 1024))//10M
//                }

            }
        return okBuilder.build()
    }



    /**
     * 普通的Https请求的客户端
     */

    val httpsClientInstance:OkHttpClient by lazy {
        createOkHttpsClient()
    }

    fun createOkHttpsClient():OkHttpClient{
        var okBuilder=OkHttpClient.Builder()
            .apply {
                connectTimeout(BaseConst.CONNECT_TIME_OUT,TimeUnit.SECONDS)

                readTimeout(BaseConst.READ_TIME_OUT,TimeUnit.SECONDS)

                writeTimeout(BaseConst.WRITE_TIME_OUT,TimeUnit.SECONDS)

                //设置接口请求拦截日志
                if (BuildConfig.isOpenLog){
                    addInterceptor(HttpLoggingInterceptor().setLevel(HttpLoggingInterceptor.Level.BODY))//日志拦截器
                }

                //Header参数拦截器
                addInterceptor(getHeaderInterceptor())

                //服务器异常拦截器
                addInterceptor(getServiceExceptionInterceptor())

                //添加Https的支持
                sslSocketFactory(sslSocketFactory, trustManager)

                //设置支持的网络协议
                protocols(listOf(Protocol.HTTP_2))

                //防止抓包软件获取接口数据
                proxy(Proxy.NO_PROXY)

                //设置缓存目录
                val cacheFile= getexternalStoreFile()
                if (cacheFile != null){
                    cache(Cache(cacheFile,10 * 1024 * 1024))//10M
                }

            }
        return okBuilder.build()
    }



    /**
     * WebSocket请求客户端
     */
    private val webSocketInstance:OkHttpClient by lazy {
        var wsOkBuilder=OkHttpClient.Builder().apply {
            //设置心跳间隔时间，维持长连接
            pingInterval(10,TimeUnit.SECONDS)
        }
        wsOkBuilder.build()
    }


    /**
     * 发起WebSocket请求
     */
    fun createWebSocketRequest(webSocketUrl:String,listener:WebSocketListener){
        val requestBuilder=Request.Builder().apply {
            url(webSocketUrl)
        }
        webSocketInstance.newWebSocket(requestBuilder.build(),listener)
    }



    /**
     * Retrofit实例
     */
    val retrofitInstance:Retrofit by lazy {
        Retrofit.Builder().apply {
            baseUrl(BuildConfig.Base_URL)
            client(httpClientInstance)
            addConverterFactory(GsonConverterFactory.create())
        }.build()
    }

    /**
     * 对外提供创建Retrofit实例的方法
     */
    fun createRetrofit(okHttpClient: OkHttpClient):Retrofit{
        return Retrofit.Builder().apply{
            baseUrl(BuildConfig.Base_URL)
            client(okHttpClient)
            addConverterFactory(GsonConverterFactory.create())
        }.build()
    }


    private fun getexternalStoreFile():File?{
        val externalStoreFile =Environment.getExternalStorageDirectory()
        if (externalStoreFile.exists()) return File(externalStoreFile,"park_network_cache")
        return null
    }


    private val sslSocketFactory: SSLSocketFactory
        get() = try {
            val sslContext= SSLContext.getInstance("SSL")
            sslContext.init(null, arrayOf(trustManager), SecureRandom())
            sslContext.socketFactory
        }catch (e:Exception){
            throw RuntimeException(e)
        }


    private val trustManager: X509TrustManager
        get()=object : X509TrustManager {
            /**
             * 检查客户端的证书
             */
            override fun checkClientTrusted(chain: Array<out X509Certificate>?, authType: String?) {
            }

            /**
             * 检查服务端的证书
             */
            override fun checkServerTrusted(chain: Array<out X509Certificate>?, authType: String?) {
                //防止抓包工具，如Fiddler, Charles抓取数据
                chain?.forEach {certificate ->
                    if (certificate.issuerX500Principal.name.contains("Charles")||
                        certificate.issuerX500Principal.name.contains("Fiddler")){
                        throw SSLHandshakeException("Fiddler或Charles证书被拒绝")
                    }
                }
            }

            override fun getAcceptedIssuers(): Array<X509Certificate> {
                return arrayOf()
            }
        }


    /**
     * 请求头拦截器
     */

    private fun getHeaderInterceptor(): Interceptor {
        return object : Interceptor {
            override fun intercept(chain: Interceptor.Chain): Response {
                //获取Token
                var token = MMKV.defaultMMKV().decodeString("token","a2208_park")
                val newBuilder = chain.request().newBuilder()
                if (token != null) {
                    newBuilder.header("token",token).build()
                }

                //获取AccessId
                var accessId= MMKV.defaultMMKV().decodeString("accessId","dd3aba2abb8b449784cf632fbedbf583")
                if (accessId!=null){
                    newBuilder.header("accessId",accessId).build()
                }

                //执行请求
                val newRequest = newBuilder.build()
                val response = chain.proceed(newRequest)

                //验证Token是否过期
                if (response.code==403||response.code==401){
                    ARouter.getInstance().build(RouterPath.PATH_LOGIN_PAGE).navigation()
                }

                return response
            }

        }
    }

    /**
     * 服务器异常拦截器
     * Interceptor属于责任链模式
     */
    private fun getServiceExceptionInterceptor(): Interceptor {
        return object: Interceptor {
            override fun intercept(chain: Interceptor.Chain): Response {
                var errorResponse = chain.proceed(chain.request())
                var responseBuilder = errorResponse.newBuilder()
                if (errorResponse.code==500){
                    var newJson= JSONObject()
                    newJson.put("code",500)
                    newJson.put("message","服务器异常，请联系客服！")
                    responseBuilder.body(newJson.toString().toResponseBody("application/json;charset=UTF-8".toMediaTypeOrNull()))
                }

                return responseBuilder.build()
            }

        }
    }

    fun clearAllRequest(){
        httpClientInstance?.dispatcher?.run {
            cancelAll()//取消请求
            executorService.shutdown()//关闭线程池
        }

        httpsClientInstance?.dispatcher?.run {
            cancelAll()//取消请求
            executorService.shutdown() //关闭线程池
        }

        webSocketInstance.dispatcher?.run {
            cancelAll()//取消请求
            executorService.shutdown()//关闭线程池
        }

        //关闭缓存
        httpClientInstance?.cache?.close()
        httpsClientInstance?.cache?.close()
        webSocketInstance?.cache?.close()


    }

}